package systemsnapshot.svn;

import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author eladh, alaah
 */
public class Logic extends Thread{
    
    // Number of columns for the index table
    private static final int COLUMNS = 4;
    
    // Program version
    public static final String VERSION = "1.1";
    
    // The HTML ouput text
    StringBuilder html = new StringBuilder();
    
    // Holder for registry query command
    private static final String REGQUERY_UTIL = "reg query ";
    
    // Linked lists to hold registry paths or cmd commnads for both server and fabric
    List<Command> serverInfoList = new ArrayList();
    List<Command> fabricInfoList = new ArrayList();
    
    // File handler
    FileWriter fstream = null;
    BufferedWriter out = null;
    
    public Logic(){
        
        // Insert Server information to a list
        serverInfoList.add(new Command("Windows Version", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\" /v ProductName", "<a href=\"#windowsVersion\">Windows Version</a>", "windowsVersion", "REG"));
        serverInfoList.add(new Command("System Info", "systeminfo", "<a href=\"#systemInfo\">System Info</a>", "systemInfo", "CMD"));
        serverInfoList.add(new Command("CPU Type", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment\" /v PROCESSOR_IDENTIFIER", "<a href=\"#cpuType\">CPU Type</a>", "cpuType", "REG"));
        serverInfoList.add(new Command("DirectX Version", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\DirectX\" /v Version", "<a href=\"#directx\">DirectX</a>", "directx", "REG"));
        serverInfoList.add(new Command("OFED Location", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\Software\\Mellanox\" /v InstalledPath", "<a href=\"#ofedLocation\">OFED Location</a>", "ofedLocation", "REG"));
        serverInfoList.add(new Command("Disk Free Space", "fsutil volume diskfree c:", "<a href=\"#diskFreeSpace\">Disk Free Space</a>", "diskFreeSpace", "CMD"));
        serverInfoList.add(new Command("hostname", "hostname", "<a href=\"#hostname\">Hostname</a>", "hostname", "CMD"));
        serverInfoList.add(new Command("System Bios Version", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\" /v SystemBiosVersion", "<a href=\"#SystemBiosVersion\">System Bios Version</a>", "SystemBiosVersion", "REG"));
        serverInfoList.add(new Command("System Bios Date", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\" /v SystemBiosDate", "<a href=\"#SystemBiosDate\">System Bios Date</a>", "SystemBiosDate", "REG"));
        serverInfoList.add(new Command("Running processes", "tasklist /fo csv /nh /V", "<a href=\"#Running processes\">Running processes</a>", "Running processes", "tasklist"));
        serverInfoList.add(new Command("Setup Mode", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\Software\\Mellanox\" /v SetupMode", "<a href=\"#setupMode\">Setup Mode</a>", "SetupMode", "REG"));
        
        // export event logs and add them to the HTML file.
        // - list of events to get
        String[] eventsList = {"IPSEC-SRV", "mlx4_bus", "mlx4_hca", "mlx4eth62", "NDIS", "NetBIOS", "NetBT", "Network Access Protection", "Network and Sharing Center", "NetworkGCW", "Networking-Correlation", "NetworkManagerTriggerProvider", "NetworkProfile", "PCI", "TCP/IP", "Tcpip", "TCPIP", "Tcpip6", "Tcpip-SQM-Provider", "TCPMon","Application Error","Windows Error Reporting"};
        
        // - build the query
        String eventsCMD = "@Name='" + eventsList[0] + "'";
        for (int i = 1; i < eventsList.length; i++){
            eventsCMD += " or @Name='" + eventsList[i] + "'";
        }       
        eventsCMD += "]]]\" /f:text";
        // - System
        serverInfoList.add(new Command("System Event Logs", "wevtutil qe System /q:\"*[System[Provider[" + eventsCMD, "<a href=\"#System Event Logs\">System Event Logs</a>", "System Event Logs", "CMD"));
        // - Application
        serverInfoList.add(new Command("Application Event Logs", "wevtutil qe Application /q:\"*[System[Provider[" + eventsCMD, "<a href=\"#Application Event Logs\">Application Event Logs</a>", "Application Event Logs", "CMD"));
        // - Setup
        serverInfoList.add(new Command("Setup Event Logs", "wevtutil qe Setup /q:\"*[System[Provider[" + eventsCMD, "<a href=\"#Setup Event Logs\">Setup Event Logs</a>", "Setup Event Logs", "CMD"));
        // --------
       
        // Insert Fabric information to a list
        fabricInfoList.add(new Command("HCA and PCI", "hostname", "<a href=\"#HCA and PCI\">HCA and PCI</a>", "HCA and PCI", "pciInfo"));   // pci info
        fabricInfoList.add(new Command("ipconfig /all", "C:\\Windows\\System32\\ipconfig.exe /all", "<a href=\"#ipconfig /all\">ipconfig /all</a>", "ipconfig /all", "CMD"));
        fabricInfoList.add(new Command("MLX4_bus Parameters", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\mlx4_bus\\Parameters\" /t REG_DWORD", "<a href=\"#MLX4_bus Parameters\">MLX4_bus Parameters</a>", "MLX4_bus Parameters", "REG_DWORD_List"));        
        fabricInfoList.add(new Command("MaxNumRssCpus", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\NDIS\\Parameters\" /v MaxNumRssCpus", "<a href=\"#MaxNumRssCpus\">MaxNumRssCpus</a>", "MaxNumRssCpus", "REG"));
        fabricInfoList.add(new Command("RssBaseCpu", REGQUERY_UTIL + "\"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\NDIS\\Parameters\" /v RssBaseCpu", "<a href=\"#RssBaseCpu\">RssBaseCpu</a>", "RssBaseCpu", "REG"));        
        fabricInfoList.add(new Command("vstat", "C:\\Program Files\\Mellanox\\MLNX_VPI\\IB\\Tools\\vstat.exe", "<a href=\"#vstat\">vstat</a>", "vstat", "CMD"));
        fabricInfoList.add(new Command("sminfo", "C:\\Program Files\\Mellanox\\MLNX_VPI\\IB\\Tools\\sminfo.exe", "<a href=\"#sminfo\">sminfo</a>", "sminfo", "CMD"));
        fabricInfoList.add(new Command("arp -a", "C:\\Windows\\System32\\ARP.exe -a", "<a href=\"#arp -a\">arp -a</a>", "arp -a", "CMD"));
        fabricInfoList.add(new Command("netstat -n", "C:\\Windows\\System32\\netstat.exe -n", "<a href=\"#netstat -n\">netstat -n</a>", "netstat -n", "CMD"));
        fabricInfoList.add(new Command("ibstat", "C:\\Program Files\\Mellanox\\MLNX_VPI\\IB\\Tools\\ibstat.exe", "<a href=\"#ibstat\">ibstat</a>", "ibstat", "CMD"));
        fabricInfoList.add(new Command("ibnetdiscover", "C:\\Program Files\\Mellanox\\MLNX_VPI\\IB\\Tools\\ibnetdiscover.exe", "<a href=\"#ibnetdiscover\">ibnetdiscover</a>", "ibnetdiscover", "CMD"));
        fabricInfoList.add(new Command("route", "route PRINT", "<a href=\"#route\">Route</a>", "route", "CMD"));
        fabricInfoList.add(new Command("netstat", "netstat -a", "<a href=\"#netstat\">netstat -a</a>", "netstat", "CMD"));
        
        
        // - Build initial HTML
        buildInitialHTML();
        // add index tables
        addIndexTable("Server information", serverInfoList);
        addIndexTable("Fabric information", fabricInfoList);
    }// constructor
    
    
    public void genHTML(){
        openStream();
        
        addCommandsResults(serverInfoList); //"Server information"
        addCommandsResults(fabricInfoList);//"Fabric information"
        
        finalizeHTMLFile(this.html.toString());
        
        closeStream();
        
        JOptionPane.showMessageDialog(null, "sys-snapshot.html created successfully!"
                + "\nThe file can be found in the same folder as this application."
                + "\n\nClick OK to terminate the application."
                + "", "File Created", JOptionPane.INFORMATION_MESSAGE);
        
        System.exit(0);
    }            
    
    private void openStream(){
        try{
            // Create file 
            fstream = new FileWriter("sys-snapshot.html");
            out = new BufferedWriter(fstream);
        }
        catch (Exception e){
            JOptionPane.showMessageDialog(null, "Could not create sys-snapshot.html", "Proccess stopped", JOptionPane.ERROR_MESSAGE);
        }
    }
    
    private void closeStream(){
        try {
            out.close();
        } catch (IOException ex) {
            Logger.getLogger(SystemSnapshotSVNUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void getParsedQuery(Command object, String prevAnchorName ,String nextAnchorName) {
        try {
            String output = runCommand(object.getProprtyPath());
            
            if (object.getType().equals("REG")) {
                    String parsedOutput = parseOutputFromRegistry(output);
                    appendToHTML(object.getName(), object.getAnchor(), parsedOutput, prevAnchorName, nextAnchorName);
            }
            if (object.getType().equals("CMD")) {
                        String parsedOutput = parseOutputFromCMD(output);
                        appendToHTML(object.getName(), object.getAnchor(), parsedOutput, prevAnchorName, nextAnchorName);
                    }
            if (object.getType().equals("pciInfo")) {
                    // gather information about the installed HCAs
                    appendToHTML(object.getName(), object.getAnchor(), getPCIInfo(), prevAnchorName, nextAnchorName);
                }
            if (object.getType().equals("REG_DWORD_List")) {
                    String parsedOutput = output.replaceAll("REG_DWORD", "");
                    String[] outputLines = parsedOutput.split("\n");
                    parsedOutput = "";
                    for (int i = 2; i < outputLines.length -2; i++){
                        String value = (outputLines[i].split("0x"))[1];
                        value = HEX2DECstring(value.replaceAll(" ", ""));
                        parsedOutput += "<br>" + outputLines[i] + "  (" + value + ")" + "</br>";
                    }
                    
                    appendToHTML(object.getName(), object.getAnchor(), parsedOutput, prevAnchorName, nextAnchorName);
                }
            if (object.getType().equals("tasklist")) {
                    String parsedOutput = "<br><table border=\"1\">";
                    
                    parsedOutput += "<th>Image Name</th>";
                    parsedOutput += "<th>PID</th>";
                    parsedOutput += "<th>Session Name</th>";
                    parsedOutput += "<th>Session#</th>";
                    parsedOutput += "<th>Mem Usage</th>";
                    parsedOutput += "<th>Status</th>";
                    parsedOutput += "<th>User Name</th>";
                    parsedOutput += "<th>CPU Time</th>";
                    parsedOutput += "<th>Window Title</th>";
                    
                    String []lines = output.split("\\n");
                            
                    for(int i=0 ; i<lines.length ; i++)
                    {
                        String []row = lines[i].split("\",\"");
                        parsedOutput += "<tr>";
                        for (int j=0; j<row.length; j++){
                            parsedOutput += "<td>" + row[j] + "</td>";
                        }
                        parsedOutput += "</tr>";
                    }
                    parsedOutput += "</table></br>";
                    
                    appendToHTML(object.getName(), object.getAnchor(), parsedOutput, prevAnchorName, nextAnchorName);
                }
        } catch (Exception ex) {
            Logger.getLogger(SystemSnapshotSVNUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
    private void appendToHTML(String propName, String anchorName, String output, String prevAnchorName ,String nextAnchorName) {
        this.html.append("<br></br><a name=\"").append(anchorName).append("\">"); // link to the output
        this.html.append("</a>\n");
        this.html.append("<h2 ").append(anchorName).append("\">"); 
        this.html.append("<u>").append(propName);
        this.html.append("</u></h2>\n");
        this.html.append("");
        this.html.append("<p>");
        this.html.append(output);
        this.html.append("</p>");
        this.html.append("");
        this.html.append("<a href=\"#").append(prevAnchorName).append("\">[<-- Previous ]</a>\n"); // prev
        this.html.append("   <a href=\"#index\">[ Back to index ]</a>\n"); // index
        this.html.append("   <a href=\"#").append(nextAnchorName).append("\">[ Next -->]</a><br></br>\n"); // next
        
    }

    private String parseOutputFromRegistry(String output) {
        StringBuilder parsedOutput = new StringBuilder();
        try{
        if (output.contains("REG_SZ")) {
            String[] seperated = output.split("REG_SZ");
            
            for (int counter = seperated.length - 1; counter > 0; counter--) {
                parsedOutput.append(seperated[counter]);
            }
        }
        if (output.contains("REG_MULTI_SZ")) {
            String[] seperated = output.split("REG_MULTI_SZ");
            
            for (int counter = seperated.length - 1; counter > 0; counter--) {
                parsedOutput.append(seperated[counter]);
            }
        }
        if (output.contains("REG_DWORD")) {
           String[] seperated = output.split("REG_DWORD");           
            for (int counter = seperated.length - 1; counter > 0; counter--) {
                parsedOutput.append(seperated[counter]);
                return HEX2DECstring(parsedOutput.toString());
            } 
        }
        }
        catch(Exception ex){}
        return parsedOutput.toString();
    }
    
    private String parseOutputFromCMD(String output) {
        output = output.replaceAll("\\n", "<br></br>");
        return output;
    }

    private String HEX2DECstring(String hex2decNoWS) {
        hex2decNoWS = hex2decNoWS.replaceAll(" ", "");
        hex2decNoWS = hex2decNoWS.replaceAll("\\s+", "");
        hex2decNoWS = hex2decNoWS.replaceAll("0x", "");
        return Integer.toString(Integer.parseInt(hex2decNoWS,16));
    }
         
    private void addCommandsResults(List<Command> list){
        for (int i = 0; i < list.size(); i++){
            if(i == 0)
            {
                getParsedQuery((Command)list.get(i), "",list.get(1).getAnchor());
            }
            else if(i == list.size()-1)
            {
                getParsedQuery((Command)list.get(i), list.get(i-1).getAnchor(), "");
            }
            else{
                getParsedQuery((Command)list.get(i), list.get(i-1).getAnchor(), list.get(i+1).getAnchor());
            }
        }
    }
    private void buildInitialHTML() {
        
        this.html.append("<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"><body style=\"line-height:60%; font-family:Courier New; font-size:14\"><head><title>System Snapshot</title>\n");
        this.html.append("</head>\n");
        this.html.append("");
        
        // link to the top of the page
        this.html.append("<br></br><a name=\"index\"></a>");
        
        this.html.append("<h1>Mellanox Technologies</h1>");
        this.html.append("<br></br><h2>Mellanox Windows System Information Snapshot Utility</h2>");
        this.html.append("<br></br><h3>Version: " + VERSION + "</h3>");
        this.html.append("<br/><hr>");
        
    }
    
    private void addIndexTable(String title, List<Command> list){
        this.html.append("<br><h2>").append(title).append("</h2></br>");
        // add the index table
        int index;
        Iterator iterator = list.iterator();
        this.html.append("<table cols=\"").append(COLUMNS).append("\" width=\"100%\" border=\"0\" bgcolor=\"#E0E0FF\"><tbody>\n");
        while(iterator.hasNext()) {
            this.html.append("<tr>\n"); // start row
            // fill items in the current row
            for (index=0; index < COLUMNS && iterator.hasNext(); index++) 
            {
                Command item = (Command)iterator.next(); 
                this.html.append("<td width=\"").append(100/COLUMNS).append("%\">").append(item.getHref()).append("</td>\n"); 
            }
            // for the last row in the table
            while (index < COLUMNS){
                this.html.append("<td> </td>\n");
                index++;
            }
            this.html.append("</tr>\n"); // end row
        }
        this.html.append("</tbody></table>\n");
        this.html.append("<br></br>\n"); 
        this.html.append("<br></br>\n");
    }

    private void finalizeHTMLFile(String htmlText) {
        this.html.append("</body>");
        this.html.append("</html>");
        try {
            out.write(htmlText);
        } catch (IOException ex) {
            Logger.getLogger(SystemSnapshotSVNUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    // gather information about the installed HACs
    private String getPCIInfo(){
        try{
        String mlx4_busEnum = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\mlx4_bus\\Enum";
        String ENUM = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\ENUM";
        String CLASS = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\class";
        
        String tmp = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + mlx4_busEnum + " /v Count"));
        int deviceCount = Integer.parseInt(tmp); // number of installed devices in the system
        
        for (int i = 0; i < deviceCount; i++){ // for all the devices
            String pciPath = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + mlx4_busEnum + " /v " + Integer.toString(i)));
            pciPath = removeNLS(pciPath);
            String pci = "\"" + ENUM + "\\" + pciPath + "\"";
            
            String driverPath = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + pci + " /v Driver"));
            driverPath = removeNLS(driverPath);
            String driver = "\"" + CLASS + "\\" + driverPath + "\"";
          
            String location  = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + pci + " /v LocationInformation"));
            location = removeNLS(location);
            
            String description = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + pci + " /v DeviceDesc"));
            description = description.replaceAll("\\n", "");
            description = description.substring(description.indexOf(';')+1);
            
            String driverDate = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + driver + " /v DriverDate"));
            location = removeNLS(location);
            
            String CapabilityFlag = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + driver + "\\Parameters /v CapabilityFlag"));
            String roce = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + driver + "\\Parameters /v EnableRoce"));
            String portType = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + driver + "\\Parameters /v PortType"));
            portType = removeNLS(portType);
            String providerName = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + driver + " /v ProviderName"));
            providerName = providerName.replaceAll("\\n", "");
            
            String driverVersion = parseOutputFromRegistry(runCommand(REGQUERY_UTIL + driver + " /v DriverVersion"));
            driverVersion = driverVersion.replaceAll("\\n", "");
            
            CapabilityFlag = removeNLS(CapabilityFlag);
            CapabilityFlag = Integer.toBinaryString(Integer.parseInt(CapabilityFlag));
            //make sure CapabilityFlag has 11 bits
            while(CapabilityFlag.length() < 11){
                CapabilityFlag = "0" + CapabilityFlag;
            }
       
            String[] vstat = runCommand("vstat").split("\n");
            String fwVer = "";
            String psid = "";
            for (int j = 0 ; j < vstat.length ; j++){
                if (vstat[j].contains("hca_idx=" + i)){
                    fwVer = vstat[j+6].split("=")[1];
                    psid = vstat[j+7].split("=")[1];
                }
            }
            
            String output = "";
            output += "<br></br>";
            
            output += "<br>Provider name:  " + providerName + "</br>";
            output += "<br>Description: " + description + "</br>";
            output += "<br>Number of ports: " + (Integer.parseInt(String.valueOf(CapabilityFlag.charAt(10)))+1) + "</br>";
            output += "<br>Driver version: " + driverVersion + "</br>";
            output += "<br>Driver Date: " + driverDate + "</br>";
            output += "<br>Firmware version: " + fwVer + "</br>";
            output += "<br>PSID: " + psid + "</br>";
            output += "<br>Location: " + location + "</br>";
            /*            
            // Analyze CapabilityFlag
            int fDpDp = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(10))); //:1; - Dual port dual protocol.    
            int fPort1IB = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(9))); //1; - Port 1 can be IB.
            int fPort2IB = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(8))); //:1; - Port 2 can be IB.
            int fPort1Eth = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(7))); //:1; - Port 1 can be ETH.
            int fPort2Eth = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(6))); //:1; - Port 2 can be ETH.
            int fPort1DoSenseAllowed = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(5))); //:1;
            int fPort2DoSenseAllowed = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(4))); //:1;
            int fPort1AutoSenseCap = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(3))); //:1;
            int fPort2AutoSenseCap = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(2))); //:1;
            int fPort1Default = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(1))); //:1;
            int fPort2Default = Integer.parseInt(String.valueOf(CapabilityFlag.charAt(0))); //:1; 
            */
            output += "<br>Ports info:</br>";
            output += "<br><table border=\"1\">";
            output += "<th> </th>";
            output += "<th>Port 1</th>";
            output += "<th>Port 2</th>";
                
                if (portType.equals("") == false) {
                output += "<tr>";
                    portType = portType.toUpperCase();
                    String[] portTypes = portType.split(",");
                    output += "<td><b>Current Port type</b></td>";
                    output += "<td>" + portTypes[0] + "</td>";
                    output += "<td>" + portTypes[1] + "</td>";
                output += "</tr>";
                }
                else
                {
                    output += "<tr>";
                    output += "<td><b>Current Port type</b></td>";
                    output += "<td>" + bin2IBETH(CapabilityFlag.charAt(1)) + "</td>";
                    output += "<td>" + bin2IBETH(CapabilityFlag.charAt(0)) + "</td>";
                    output += "</tr>";
                }
            
                output += "<tr>";
                    output += "<td>ROCE enabled</td>";
                    output += "<td>" + bin2YESNO(roce.charAt(0)) + "</td>";
                    output += "<td>" + bin2YESNO(roce.charAt(2)) + "</td>";
                output += "</tr>";
                
                output += "<tr>";
                    output += "<td>Port can be IB</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(9)) + "</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(8)) + "</td>";
                output += "</tr>";
                
                output += "<tr>";
                    output += "<td>Port can be ETH</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(7)) + "</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(6)) + "</td>";
                output += "</tr>";
                
                output += "<tr>";
                    output += "<td>Port Do Sense Allowed</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(5)) + "</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(4)) + "</td>";
                output += "</tr>";
                
                output += "<tr>";
                    output += "<td>Port Auto Sense Cap</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(3)) + "</td>";
                    output += "<td>" + bin2YESNO(CapabilityFlag.charAt(2)) + "</td>";
                output += "</tr>";
                
                output += "<tr>";
                    output += "<td>Port Default type</td>";
                    output += "<td>" + bin2IBETH(CapabilityFlag.charAt(1)) + "</td>";
                    output += "<td>" + bin2IBETH(CapabilityFlag.charAt(0)) + "</td>";
                output += "</tr>";
                
            output += "</table></br>";
            
            output += "<br>----------------------------------------------</br>";
            output += "<br></br>";
            return output;
        }
        
        
        }
        catch(Exception ex){
            return "<br>" + ex.getLocalizedMessage() + "</br>";
        }
        return "<br></br>";
    }
    
    private String removeNLS(String str){
        str = str.replaceAll("\n", "");
        return str.replaceAll(" ", "");
    }
    
    private String bin2YESNO(char ch){
        if (ch == '1'){
            return "YES";
        }
        else{
            return "NO";
        }
    }
    
    private String bin2IBETH(char ch){
        if (ch == '1'){
            return "ETH";
        }
        else{
            return "IB";
        }
    }
    
    private String runCommand(String command){
        try {
            Process process = Runtime.getRuntime().exec(command);
            BufferedReader Resultset = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            StringBuilder output = new StringBuilder();
            try {
                while ((line = Resultset.readLine()) != null) {
                    output.append(line);
                    output.append("\n");
                }
                return output.toString();
            } 
            catch (IOException ex) {
                Logger.getLogger(SystemSnapshotSVNUI.class.getName()).log(Level.SEVERE, null, ex);
                return "";
            }
        } 
        catch (IOException ex) {
            Logger.getLogger(SystemSnapshotSVNUI.class.getName()).log(Level.SEVERE, null, ex);
            return "";
        }
    }
    
    
    @Override
    public void run() {
        try{
            this.genHTML();
        }
        catch (Exception ex){
            JOptionPane.showMessageDialog(null, "Could not generate HTML", "Proccess stopped", JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(SystemSnapshotSVNUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void stopThread(){
        closeStream();
        this.stop();
    }
    
    public static String getVersion() {
        return VERSION;
    }
}
